home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / uae / uae-0.4.3 / hardfile.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  9KB  |  388 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * AutoConfig devices
  5.   *
  6.   * (c) 1995 Bernd Schmidt
  7.   */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <assert.h>
  12.  
  13. #ifdef __unix
  14. #include <unistd.h>
  15. #include <fcntl.h>
  16. #endif
  17.  
  18. #include "config.h"
  19. #include "amiga.h"
  20. #include "options.h"
  21. #include "events.h"
  22. #include "memory.h"
  23. #include "custom.h"
  24. #include "newcpu.h"
  25. #include "disk.h"
  26. #include "xwin.h"
  27. #include "autoconf.h"
  28. #include "hardfile.h"
  29.  
  30. static int opencount = 0;
  31. static int uaedevfd;
  32. static int numtracks = 512;
  33.  
  34. static ULONG dosname, uaedevname;
  35.  
  36. static ULONG hardfile_init(void)
  37. {
  38.     ULONG tmp1, tmp2, tmp3,configdev;
  39.     bool have36 = true;
  40.     ULONG retval = regs.d[0];
  41.  
  42.     if (!automount_uaedev)
  43.     return retval;
  44.  
  45.     regs.d[0] = 88; regs.d[1] = 1; /* MEMF_PUBLIC */
  46.     tmp1 = CallLib (regs.a[6], -198); /* AllocMem() */
  47.     if (tmp1 == 0) {
  48.     fprintf(stderr, "Not enough memory for uae.device!\n");
  49.     return 0;
  50.     }
  51.     /* Open expansion.lib */
  52.     regs.d[0] = 36; /* Let's try this... */
  53.     regs.a[1] = explibname;
  54.     regs.a[4] = CallLib (regs.a[6], -552); /* OpenLibrary() */
  55.     if (regs.a[4])
  56.     have36 = true;
  57.     else {
  58.     regs.d[0] = 0;
  59.     regs.a[1] = explibname;
  60.     regs.a[4] = CallLib (regs.a[6], -552); /* OpenLibrary() */
  61.     }
  62.     put_long (tmp1, dosname);
  63.     put_long (tmp1+4, uaedevname);
  64.     put_long (tmp1+8, 0); /* Unit no. */
  65.     put_long (tmp1+12, 0); /* Device flags */
  66.     put_long (tmp1+16, 16); /* Env. size */
  67.     put_long (tmp1+20, 128); /* 512 bytes/block */
  68.     put_long (tmp1+24, 0); /* unused */
  69.     put_long (tmp1+28, 1); /* heads */
  70.     put_long (tmp1+32, 1); /* unused */
  71.     put_long (tmp1+36, 32); /* secs per track */
  72.     put_long (tmp1+40, 1); /* reserved blocks */
  73.     put_long (tmp1+44, 0); /* unused */
  74.     put_long (tmp1+48, 0); /* interleave */
  75.     put_long (tmp1+52, 0); /* lowCyl */
  76.     put_long (tmp1+56, 511); /* upperCyl */
  77.     put_long (tmp1+60, 0); /* Number of buffers */
  78.     put_long (tmp1+64, 0); /* Buffer mem type */
  79.     put_long (tmp1+68, 0x7FFFFFFF); /* largest transfer */
  80.     put_long (tmp1+72, ~1); /* addMask (?) */
  81.     put_long (tmp1+76, (ULONG)-1); /* bootPri */
  82.     if (have36)
  83.     put_long (tmp1+80, 0x444f5301); /* DOS\1 */
  84.     else
  85.     put_long (tmp1+80, 0x444f5300); /* DOS\0 */
  86.   
  87.   
  88.     put_long (tmp1+84, 0); /* pad */
  89.     regs.a[0] = tmp1;
  90.     tmp2 = CallLib (regs.a[4], -144); /* MakeDosNode() */
  91.  
  92.         configdev = CallLib(regs.a[4], -48); /* AllocConfigDev() */
  93.  
  94.         /* hier init der Configdev */
  95.  
  96.  
  97.  
  98.  
  99.     regs.a[0] = tmp2;
  100.     regs.d[0] = (ULONG)-1;
  101.     regs.a[1] = configdev;
  102.     regs.d[1] = 0;
  103. #if 0
  104.     CallLib (regs.a[4], -150); /* AddDosNode() */
  105. #endif
  106.  
  107.  
  108. #if 1
  109. #if 1
  110.     if (have36)
  111.     CallLib (regs.a[4], /*-150*/ -36); /* AddDosNode() */
  112.     else {
  113. #endif
  114.         /* We could also try to call AddBootNode() here - but we don't have
  115.      * a ConfigDev. */
  116.     regs.d[0] = 20;
  117.     regs.d[1] = 0;
  118.     tmp3 = CallLib (regs.a[6], -198);
  119.     if (tmp3 == 0) {
  120.         fprintf(stderr, "Not enough memory for uae.device bootnode!\n");
  121.         return 0;
  122.     }
  123.     put_word (tmp3 + 14, 0);
  124.     put_long (tmp3 + 16, tmp2);
  125.     put_word (tmp3 + 8, 0x1005);
  126.     put_long (tmp3 + 10, 0);
  127.     put_long (tmp3 + 0, 0);
  128.     put_long (tmp3 + 4, 0);
  129.     regs.a[0] = regs.a[4] + 74; /* MountList */
  130.     regs.a[1] = tmp3;
  131.     CallLib (regs.a[6], -270); /* Enqueue() */
  132. #if 1
  133.     }
  134. #endif
  135. #endif
  136.     
  137.     regs.a[1] = tmp1;
  138.     regs.d[0] = 88;
  139.     CallLib (regs.a[6], -210); /* FreeMem() */
  140.     
  141.     regs.a[1] = regs.a[4];
  142.     CallLib (regs.a[6], -414); /* CloseLibrary() */
  143.     
  144.     return retval;
  145. }
  146.     
  147. static ULONG hardfile_open(void)
  148. {
  149.     CPTR tmp1 = regs.a[1]; /* IOReq */
  150.     
  151.     /* Check unit number */
  152.     if (regs.d[0] == 0) {        
  153.     opencount++;
  154.     put_word (regs.a[6]+32, get_word (regs.a[6]+32) + 1);
  155.     put_long (tmp1+24, 0); /* io_Unit */
  156.     put_byte (tmp1+31, 0); /* io_Error */
  157.     put_byte (tmp1+8, 7); /* ln_type = NT_REPLYMSG */
  158.     return 0;
  159.     }
  160.  
  161.     put_long (tmp1+20, (ULONG)-1);
  162.     put_byte (tmp1+31, (UBYTE)-1);
  163.     return (ULONG)-1;
  164. }
  165.  
  166. static ULONG hardfile_close(void)
  167. {
  168.     opencount--;
  169.     put_word (regs.a[6]+32, get_word (regs.a[6]+32) - 1);
  170.  
  171.     return regs.d[0];
  172. }
  173.     
  174. static ULONG hardfile_expunge(void)
  175. {
  176.     return 0; /* Simply ignore this one... */
  177. }
  178.     
  179. static ULONG hardfile_beginio(void)
  180. {
  181.     ULONG tmp1, tmp2, dataptr, offset;
  182.     ULONG retval = regs.d[0];
  183.  
  184.     tmp1 = regs.a[1];
  185.     put_byte (tmp1+8, 5); /* set ln_type to NT_MESSAGE */
  186.     put_byte (tmp1+31, 0); /* no error yet */
  187.     tmp2 = get_word (tmp1+28); /* io_Command */
  188.     switch (tmp2) {
  189.      case 2: /* Read */
  190.     dataptr = get_long (tmp1 + 40);
  191.     if (dataptr & 1)
  192.         goto bad_command;
  193.     offset = get_long (tmp1 + 44);
  194.     if (offset & 511)
  195.         goto bad_command;
  196.     tmp2 = get_long (tmp1 + 36); /* io_Length */
  197.     if (tmp2 & 511)
  198.         goto bad_command;
  199.     if (tmp2 + offset > (ULONG)numtracks * 32 * 512)
  200.         goto bad_command;
  201.     
  202.     put_long (tmp1 + 32, tmp2); /* set io_Actual */
  203.     lseek (uaedevfd, offset, SEEK_SET);
  204.     while (tmp2) {
  205.         int i;
  206.         char buffer[512];
  207.         read (uaedevfd, buffer, 512);
  208.         for (i = 0; i < 512; i++, dataptr++)
  209.         put_byte(dataptr, buffer[i]);
  210.         tmp2 -= 512;
  211.     }
  212.     break;
  213.         
  214.      case 3: /* Write */
  215.      case 11: /* Format */
  216.     dataptr = get_long (tmp1 + 40);
  217.     if (dataptr & 1)
  218.         goto bad_command;
  219.     offset = get_long (tmp1 + 44);
  220.     if (offset & 511)
  221.         goto bad_command;
  222.     tmp2 = get_long (tmp1 + 36); /* io_Length */
  223.     if (tmp2 & 511)
  224.         goto bad_command;
  225.     if (tmp2 + offset > (ULONG)numtracks * 32 * 512)
  226.         goto bad_command;
  227.     
  228.     put_long (tmp1 + 32, tmp2); /* set io_Actual */
  229.     lseek (uaedevfd, offset, SEEK_SET);
  230.     while (tmp2) {
  231.         char buffer[512];
  232.         int i;
  233.         for (i=0; i < 512; i++, dataptr++)
  234.         buffer[i] = get_byte(dataptr);
  235.         write (uaedevfd, buffer, 512);
  236.         tmp2 -= 512;
  237.     }
  238.     break;
  239.     
  240.     bad_command:
  241.     break;
  242.     
  243.      case 18: /* GetDriveType */
  244.     put_long (tmp1 + 32, 1); /* not exactly a 3.5" drive, but... */
  245.     break;
  246.     
  247.      case 19: /* GetNumTracks */
  248.     put_long (tmp1 + 32, numtracks); 
  249.     break;
  250.     
  251.     /* Some commands that just do nothing and return zero */
  252.      case 4: /* Update */
  253.      case 5: /* Clear */
  254.      case 9: /* Motor */
  255.      case 10: /* Seek */
  256.      case 12: /* Remove */
  257.      case 13: /* ChangeNum */
  258.      case 14: /* ChangeStatus */
  259.      case 15: /* ProtStatus */
  260.      case 20: /* AddChangeInt */
  261.      case 21: /* RemChangeInt */
  262.     put_long (tmp1+32, 0); /* io_Actual */
  263.     retval = 0;
  264.     break;
  265.     
  266.      default:
  267.     /* Command not understood. */
  268.     put_byte (tmp1+31, (UBYTE)-3); /* io_Error */
  269.     retval = 0;
  270.     break;
  271.     }
  272.     if ((get_byte (tmp1+30) & 1) == 0) {
  273.     /* Not IOF_QUICK -- need to ReplyMsg */
  274.     regs.a[1] = tmp1;
  275.     CallLib (get_long(4), -378);
  276.     }
  277.     return retval;
  278. }
  279.     
  280. static ULONG hardfile_abortio(void)
  281. {
  282.     return (ULONG)-3;
  283. }
  284.  
  285. void hardfile_install(void)
  286. {
  287.     ULONG devid, functable, datatable, inittable, begin, end;
  288.     ULONG initroutine, openfunc, closefunc, expungefunc;
  289.     ULONG nullfunc, beginiofunc, abortiofunc;
  290.  
  291.     uaedevfd = open ("hardfile", O_RDWR);
  292.     
  293.     if (uaedevfd < 0)
  294.         return;
  295.     
  296.     uaedevname = ds("uae.device");
  297.     devid = ds("uae 0.4"); /* ID */
  298.     dosname = ds("UAEHF"); /* This is the DOS name */
  299.  
  300.     begin = here();
  301.     dw(0x4AFC); /* RTC_MATCHWORD */
  302.     dl(begin); /* our start address */
  303.     dl(0); /* Continue scan here */
  304.     dw(0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
  305.     dw(0x0305); /* NT_DEVICE; pri 5 */
  306.     dl(uaedevname); /* name */
  307.     dl(devid); /* ID */
  308.     dl(here() + 4); /* Init area: directly after this */
  309.     /* Init area starts here */
  310.     dw(0x0000); /* Not really sure what to put here */
  311.     dw(0x0100);
  312.     inittable = here();
  313.     dl(0); dl(0); dl(0); /* skip 3 longs */
  314.  
  315.     /* InitRoutine */
  316.     initroutine = here();
  317.     calltrap(deftrap(hardfile_init)); dw(RTS);
  318.  
  319.     /* Open */
  320.     openfunc = here();
  321.     calltrap(deftrap(hardfile_open)); dw(RTS);
  322.  
  323.     /* Close */
  324.     closefunc = here();
  325.     calltrap(deftrap(hardfile_close)); dw(RTS);
  326.  
  327.     /* Expunge */
  328.     expungefunc = here();
  329.     calltrap(deftrap(hardfile_expunge)); dw(RTS);
  330.     
  331.     /* Null */
  332.     nullfunc = here();
  333.     dw(0x7000); /* return 0; */
  334.     dw(RTS);
  335.  
  336.     /* BeginIO */
  337.     beginiofunc = here();
  338.     calltrap(deftrap(hardfile_beginio)); dw(RTS);
  339.  
  340.     /* AbortIO */
  341.     abortiofunc = here();
  342.     calltrap(deftrap(hardfile_abortio)); dw(RTS);
  343.     
  344.     /* FuncTable */
  345.     functable = here();
  346.     dl(openfunc); /* Open */
  347.     dl(closefunc); /* Close */
  348.     dl(expungefunc); /* Expunge */
  349.     dl(nullfunc); /* Null */
  350.     dl(beginiofunc); /* BeginIO */
  351.     dl(abortiofunc); /* AbortIO */
  352.     dl(0xFFFFFFFF); /* end of table */
  353.  
  354.     /* DataTable */
  355.     datatable = here();
  356.     dw(0xE000); /* INITBYTE */
  357.     dw(0x0008); /* LN_TYPE */
  358.     dw(0x0300); /* NT_DEVICE */
  359.     dw(0xC000); /* INITLONG */
  360.     dw(0x000A); /* LN_NAME */
  361.     dl(uaedevname);
  362.     dw(0xE000); /* INITBYTE */
  363.     dw(0x000E); /* LIB_FLAGS */
  364.     dw(0x0600); /* LIBF_SUMUSED | LIBF_CHANGED */
  365.     dw(0xD000); /* INITWORD */
  366.     dw(0x0014); /* LIB_VERSION */
  367.     dw(0x0004); /* 0.4 */
  368.     dw(0xD000);
  369.     dw(0x0016); /* LIB_REVISION */
  370.     dw(0x0000);
  371.     dw(0xC000);
  372.     dw(0x0018); /* LIB_IDSTRING */
  373.     dl(devid);
  374.     dw(0x0000); /* end of table */
  375.  
  376.     end = here();
  377.  
  378.     org(inittable);
  379.     dl(functable);
  380.     dl(datatable);
  381.     dl(initroutine);
  382.  
  383.     org(begin + 6);
  384.     dl(end);
  385.  
  386.     org(end);
  387. }
  388.